﻿using PBO.Data.SQLite;
using PBO.Data.Util;
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using PBO.Data.PokemonOnline;

namespace PBO.Data
{
    [Serializable()]
    public class TeamData : DataStream, ICloneable, IEquatable<TeamData>
    {
        public PokemonCustomInfo[] Pokemons { get; private set; }

        public TeamData()
        {
            this.Pokemons = Enumerable.Repeat(PokemonCustomInfo.EmptyPokemon, 6).ToArray();
        }

        #region ICloneable

        public TeamData Clone()
        {
            TeamData data = new TeamData();
            for (int i = 0; i < Pokemons.Length; i++)
            {
                data.Pokemons[i] = (PokemonCustomInfo)Pokemons[i].Clone();
            }
            return data;
        }

        object ICloneable.Clone()
        {
            return this.Clone();
        }

        #endregion

        #region IEquatable

        public bool Equals(TeamData other)
        {
            if (other == null) return false;
            for (int i = 0; i < 6; i++)
            {
                if (!Pokemons[i].Equals(other.Pokemons[i])) return false;
            }
            return true;
        }

        #endregion

        #region file

        public static TeamData FromFile(string path)
        {
            TeamData team = null;

            if (path.EndsWith(".tp"))
            {
                return POHelper.ReadFile(path);
            }
            else if (path.EndsWith(".ptd"))
            {
                return From0791(path);
            }

            using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                using (var ms = DataStreamHelper.Decrypt(fs))
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    var reader = new BinaryReader(ms);
                    team = FromBinary<TeamData>(reader);
                }
                fs.Close();
            }
            return team;
        }

        public void SaveFile(string path)
        {
            using (var ms = new MemoryStream())
            {
                this.Save(ms);
                DataStreamHelper.Encrypt(ms, path);
            }
        }

        #endregion

        #region send

        public byte[] ToBytes()
        {
            byte[] bytes;
            using (MemoryStream stream = new MemoryStream())
            {
                Save(stream);
                bytes = new byte[(int)stream.Position];
                Array.Copy(stream.GetBuffer(), bytes, bytes.Length);
            }
            return bytes;
        }

        public static TeamData FromBytes(byte[] bytes)
        {
            TeamData team = null;
            using (MemoryStream stream = new MemoryStream())
            {
                stream.Write(bytes, 0, bytes.Length);
                stream.Seek(0, SeekOrigin.Begin);
                var reader = new BinaryReader(stream);
                team = FromBinary<TeamData>(reader);
            }
            return team;
        }

        #endregion

        #region 0791

        public static TeamData From0791(string path)
        {
            TeamData team = null;
            using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                using (var ms = DataStreamHelper.Decrypt(fs))
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    var reader = new BinaryReader(ms);
                    team = BinaryLoad0791(reader);
                }
                fs.Close();
            }
            return team;
        }

        private static TeamData BinaryLoad0791(BinaryReader reader)
        {
            reader.ReadString();
            reader.ReadString();
            var team = new TeamData();
            for (int i = 0; i < team.Pokemons.Length; i++)
            {
                team.Pokemons[i] = PokemonCustomInfo.Load0791(reader);
            }
            return team;
        }

        internal void BinarySave0791(BinaryWriter writer)
        {
            writer.Write("Chobits");

            throw new NotImplementedException();
        }

        #endregion

        #region Binary

        public override void BinaryLoad(BinaryReader reader)
        {
            for (int i = 0; i < this.Pokemons.Length; i++)
            {
                this.Pokemons[i] = FromBinary<PokemonCustomInfo>(reader);
            }
        }

        public override void BinarySave(BinaryWriter writer)
        {
            foreach (PokemonCustomInfo pm in Pokemons)
            {
                pm.BinarySave(writer);
            }
        }

        #endregion

        #region sort

        public void Sort()
        {
            int emptyCount = this.Pokemons.Count(p => p.Identity == 0);
            if (emptyCount == 0 || emptyCount == this.Pokemons.Length) return;

            var list = new List<PokemonCustomInfo>();
            list.AddRange(this.Pokemons.Where(p => p.Identity != 0));

            int count = this.Pokemons.Length - list.Count;
            for (int i = 0; i < count; i++)
            {
                list.Add(PokemonCustomInfo.EmptyPokemon);
            }
            this.Pokemons = list.ToArray();
        }

        #endregion

    }
}
